package com.tdu.spider.biz.service.same;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tdu.spider.biz.service.same.vo.*;
import com.tdu.spider.biz.util.ConvertUtils;
import com.tdu.spider.dao.SameSenseRepository;
import com.tdu.spider.dao.SameUserRepository;
import com.tdu.spider.model.SameChannelDO;
import com.tdu.spider.model.SameLikeCountVO;
import com.tdu.spider.model.SameSenseDO;
import com.tdu.spider.model.SameUserDO;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Same统计分析服务
 *
 * @author tangdu
 * @version $: SameAnalyseService.java, v 0.1 2018年02月03日 下午6:12 tangdu Exp $
 */
@Service
public class SameAnalyseService {

    @Autowired
    private SameSenseRepository sameSenseRepository;

    @Autowired
    private SameUserRepository sameUserRepository;

    @Autowired
    private SameApiService sameApiService;

    @Autowired
    private MongoTemplate mongoTemplate;


    public SameAnalyseInfoVO analyseInfoVO(SameAnalyseQueryVO sameAnalyseQueryVO) throws Exception{
            //step0:根据用户ID查询用户信息
            SameUserDO sameUserDO = sameUserRepository.findById(sameAnalyseQueryVO.getUserId()).get();
            if(sameUserDO==null){
                UserVO userVO = sameApiService.queryUserDetail(sameAnalyseQueryVO.getUserId());
                if(userVO==null){
                    return null;
                }
                sameUserDO= ConvertUtils.copy(userVO,SameUserDO.class);
            }


            SameAnalyseInfoVO sameAnalyseInfoVO = new SameAnalyseInfoVO();
            sameAnalyseInfoVO.setUserId(sameUserDO.getId());
            sameAnalyseInfoVO.setUserName(sameUserDO.getUsername());
            sameAnalyseInfoVO.setRegisterDate(new Date(sameUserDO.getJoin_at()*1000));
            sameAnalyseInfoVO.setUserAvatar(sameUserDO.getAvatar());
            //step1:找出用户所有文章记录
            List<SameSenseDO> sameSenseDOS = sameSenseRepository.findByUser_id(sameAnalyseQueryVO.getUserId());
            if (CollectionUtils.isEmpty(sameSenseDOS)) {
                return sameAnalyseInfoVO;
            }

            //step2:统计分析各项指标
            sameAnalyseInfoVO.setRowdate(DateTime.now().toDate());
            sameAnalyseInfoVO.setPublishSenseNum(sameSenseDOS.size());
            Map<SameChannelDO, Integer> cos = Maps.newHashMap();
            SameSenseDO moreStarSense = null;
            SameSenseDO firstPublishSense = null;
            SameSenseDO maxPublishSense = null;
            int dianzanNum=0;
            int viewsNum=0;

            for (SameSenseDO senseDO : sameSenseDOS) {
                dianzanNum+=senseDO.getLikes();
                viewsNum+=senseDO.getViews();

                //统计最受欢迎
                if (moreStarSense == null) {
                    moreStarSense = senseDO;
                } else {
                    if (moreStarSense.getLikes() + moreStarSense.getViews() < senseDO.getLikes() + senseDO.getViews()) {
                        moreStarSense = senseDO;
                    }
                }
                //统计文章最多内容
                if (cos.containsKey(senseDO.getChannel())) {
                    cos.replace(senseDO.getChannel(), cos.get(senseDO.getChannel()) + 1);
                } else {
                    cos.put(senseDO.getChannel(), 1);
                }
                //最早Sense发布时间
                if (firstPublishSense == null) {
                    firstPublishSense = senseDO;
                } else {
                    if (senseDO.getCreated_at()<firstPublishSense.getCreated_at()) {
                        firstPublishSense = senseDO;
                    }
                }
                //最晚发贴时间
                if (maxPublishSense == null) {
                    maxPublishSense = senseDO;
                } else {
                    if (senseDO.getCreated_at()>maxPublishSense.getCreated_at()) {
                        maxPublishSense = senseDO;
                    }
                }
            }
            List<SameChannelVO> channelVOS= Lists.newArrayList();
            Map.Entry<SameChannelDO, Integer> integerEntryMax=null;
            for (Map.Entry<SameChannelDO, Integer> integerEntry : cos.entrySet()) {
                if(integerEntryMax==null){
                    integerEntryMax=integerEntry;
                }else{
                    if(integerEntry.getValue()>integerEntryMax.getValue()) {
                        integerEntryMax = integerEntry;
                    }
                }
                SameChannelVO activeChannel = ConvertUtils.copy(integerEntry.getKey(), SameChannelVO.class);
                activeChannel.setCount(integerEntry.getValue());
                channelVOS.add(activeChannel);
            }
            if(integerEntryMax!=null) {
                SameChannelVO activeChannel = ConvertUtils.copy(integerEntryMax.getKey(), SameChannelVO.class);
                activeChannel.setCount(integerEntryMax.getValue());
                sameAnalyseInfoVO.setActiveChannel(activeChannel);
            }
            sameAnalyseInfoVO.setDianzanNum(dianzanNum);
            sameAnalyseInfoVO.setViewsNum(viewsNum);
            sameAnalyseInfoVO.setChannelVOS(channelVOS);
            setSameAnalyseChannelChart(sameAnalyseInfoVO);
            sameAnalyseInfoVO.setFirstPublishSense(ConvertUtils.copy(firstPublishSense, SenSeVO.class));
            sameAnalyseInfoVO.setMaxPublishSense(ConvertUtils.copy(maxPublishSense, SenSeVO.class));
            sameAnalyseInfoVO.setMoreStarSense(ConvertUtils.copy(moreStarSense, SenSeVO.class));
            sameAnalyseInfoVO.setAttentionChannelNum(sameUserDO.getChannels());
            //step3:统计最关心我的人
            Criteria criteria= Criteria.where("targetUserId");
            criteria.is(sameUserDO.getId());
            Aggregation aggregation=Aggregation.newAggregation(
                    Aggregation.match(criteria),
                    Aggregation.project("userId","username","avatar","usernum"),
                    Aggregation.group("userId","username","avatar").count().as("usernum"),
                    Aggregation.sort(Sort.Direction.DESC, "usernum"),
                    Aggregation.limit(3)
            );
            AggregationResults<SameLikeCountVO> sameLikeCountVOS = mongoTemplate.aggregate(aggregation, "same_sense_like", SameLikeCountVO.class);
            if(!CollectionUtils.isEmpty(sameLikeCountVOS.getMappedResults())){
                sameAnalyseInfoVO.setMustStarUsers(sameLikeCountVOS.getMappedResults());
            }
            return sameAnalyseInfoVO;
    }

    public void setSameAnalyseChannelChart(SameAnalyseInfoVO sameAnalyseInfoVO) {
        List<String> channels= Lists.newArrayList();
        List<SameAnalyseInfoVO.SameAnalyseChannelChartRow> channelNums=Lists.newArrayList();
        List<SameChannelVO> channelVOS = sameAnalyseInfoVO.getChannelVOS();
        if(!CollectionUtils.isEmpty(channelVOS)){
            channelVOS.sort(new Comparator<SameChannelVO>() {
                @Override
                public int compare(SameChannelVO o1, SameChannelVO o2) {
                    if(o1.getCount().equals(o2.getCount())){
                        return 0;
                    }
                    return o1.getCount()<o2.getCount() ? 1:-1;
                }
            });
            List<SameChannelVO> _channelVOS=Lists.newArrayList(channelVOS);
            if(channelVOS.size()>5){
                _channelVOS=channelVOS.subList(0,5);
            }
            Map<String,Integer> ms= Maps.newHashMap();
            for (SameChannelVO channelVO : _channelVOS) {
                channels.add(channelVO.getName());
                SameAnalyseInfoVO.SameAnalyseChannelChartRow sameAnalyseChannelChartRow=new SameAnalyseInfoVO.SameAnalyseChannelChartRow();
                sameAnalyseChannelChartRow.setName(channelVO.getName());
                sameAnalyseChannelChartRow.setValue(channelVO.getCount());
                channelNums.add(sameAnalyseChannelChartRow);
            }
            SameAnalyseInfoVO.SameAnalyseChannelChart sameAnalyseChannelChart = new SameAnalyseInfoVO.SameAnalyseChannelChart();
            sameAnalyseChannelChart.setChannelNums(channelNums);
            sameAnalyseChannelChart.setChannels(channels);
            sameAnalyseInfoVO.setSameAnalyseChannelChart(sameAnalyseChannelChart);
        }
    }

}
